package com.qf.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qf.dao.TbRoleRepository;
import com.qf.dao.TbUserRepository;
import com.qf.dao.TbUserRoleMapper;
import com.qf.dao.TbUserRoleRepository;
import com.qf.pojo.entity.TbRole;
import com.qf.pojo.entity.TbUser;
import com.qf.pojo.req.TbUserReq;
import com.qf.pojo.req.TbUserRoleReq;
import com.qf.pojo.resp.BasePermissionResp;
import com.qf.pojo.resp.BasePermissionValueResp;
import com.qf.pojo.resp.BaseResp;
import com.qf.service.TbUserService;
import com.qf.utils.MD5Utils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
@Service
public class TbUserServiceImpl implements TbUserService {
    //用户接口
    @Autowired
    TbUserRepository tbUserRepository;
    //角色接口
    @Autowired
    TbRoleRepository tbRoleRepository;
    //用户角色接口
    @Autowired
    TbUserRoleRepository tbUserRoleRepository;
    @Autowired
    TbUserRoleMapper tbUserRoleMapper;


    /**
     * 查询所有用户
     * @param page 当前页
     * @param size 当前页显示条数
     * @return
     */
    @Override
    public BaseResp findAll(Integer page, Integer size) {
        PageRequest of = PageRequest.of(page - 1, size);
        Page<TbUser> all = tbUserRepository.findAll(of);
        List<TbUser> list = all.getContent();
        long total = all.getTotalPages();
        return new BaseResp(1,"success",list,total);
    }

    /**
     * 根据用户id 删除用户
     * @param id 用户编号
     * @return
     */
    @Override
    public BaseResp deleteById(Integer id) {
        tbUserRepository.deleteById(id);
        tbUserRoleRepository.deleteByUserId(id);
        return new BaseResp().SUCCESS();
    }

    /**
     * 修改或者新增用户
     * @param tbUserReq 请求用户对象
     * @return
     */
    @Override
    public BaseResp updateOrSave(TbUserReq tbUserReq) {
        TbUser tbUser = new TbUser();
        BeanUtils.copyProperties(tbUserReq,tbUser);
        //需要对前端传过来的参数进行加密处理
        //1.判断前端传来的参数是否经过加密处理,和数据库中的密码进行比较
        String md5 = MD5Utils.CreateMD5(tbUserReq.getUsername(), tbUserReq.getPassword());
        //2.判断轻轻对象的id是否为空,为空表示新增,不为空表示修改
        if (tbUserReq.getId() != null){
            tbUser.setUpdateTime(new Date());
            //通过请求对象的id查询该对象
            Optional<TbUser> byId = tbUserRepository.findById(tbUserReq.getId());
            TbUser user = byId.get();
            //比较前端传入的密码和数据库中的密码
            //如果密码不一致,说明用户修改了密码
            if (!md5.equals(tbUserReq.getPassword())){
                tbUser.setPassword(md5);
            }
        }else{
            tbUser.setCreateTime(new Date());
            //对新增用户密码进行加密
            tbUser.setPassword(md5);
        }
        tbUserRepository.saveAndFlush(tbUser);
        return new BaseResp().SUCCESS();
    }

    /**
     * 根据用户id查询用户角色
     * @param id 用户id
     * @return
     */
    @Override
    public BaseResp findRoleByUserId(Integer id) {
        //1.封装了所有的角色的集合
        //1.1查询数据库中所有的角色
        List<TbRole> all = tbRoleRepository.findAll();
        //1.2建立角色列表,并将数据库中的所有角色放入其中
        List roleList = new ArrayList();
        //1.3放入角色
        for (TbRole list:all) {
            BasePermissionResp basePermissionResp = new BasePermissionResp();
            basePermissionResp.setKey(list.getId());
            basePermissionResp.setLabel(list.getRoleName());
            basePermissionResp.setDisable(false);
            roleList.add(basePermissionResp);

        }
        //2.查询该用户所拥有的所有角色id
        List<Integer> roleId = tbUserRoleRepository.findRoleIdByUserId(id);
        //3.将所有的用户角色以及角色编号放入公共返回值中
        BasePermissionValueResp basePermissionValueResp = new BasePermissionValueResp();
        basePermissionValueResp.setData(roleList);
        basePermissionValueResp.setValue(roleId);
        return new BaseResp(1,"success",basePermissionValueResp,null);
    }

    /**
     * 修改或新增用户角色
     * @param tbUserRoleReq 用户角色请求对象
     * @return 响应对象
     */
    @Override
    public BaseResp updateUserRole(TbUserRoleReq tbUserRoleReq) {
        //1.获取用户id
        Integer userid = tbUserRoleReq.getUserid();
        //2.获取该用户对应的所有角色id
        List<Integer> userRoleIdList = tbUserRoleReq.getUserRoleList();
        //3.通过角色对应的用户id,查询该用户的所有角色
        List<Integer> roleIdByUserId = tbUserRoleRepository.findRoleIdByUserId(userid);
        //4.进行判断
        if (roleIdByUserId != null){
            //4.1该用户角色列表不为空,则说明该用户拥有角色,我们需将其角色清空
            tbUserRoleMapper.deleteRoleByUserId(userid);
        }
        //5.建立新的逻辑,使用动态sql语句修改或新增新的角色(foreach的使用)
        if (userRoleIdList != null && userRoleIdList.size()>0){
            tbUserRoleMapper.addUserRole(tbUserRoleReq);
        }
        return new BaseResp().SUCCESS();
    }

    /**
     * 登录操作
     * @param tbUserReq 用户请求对象
     * @return 响应对象
     */
    @Override
    public BaseResp login(TbUserReq tbUserReq) {
        //1.将前台数据传入的用户名及密码放入到UserPasswordToken中
        UsernamePasswordToken user = new UsernamePasswordToken(tbUserReq.getUsername(), tbUserReq.getPassword());
        //2.使用主体进行登录操作,主体需要从SecurityUtils中获取
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(user);
        } catch (UnknownAccountException unknownAccountException) {
            return new BaseResp(0,"账号错误!",null,null);
        }catch (IncorrectCredentialsException incorrectCredentialsException){
            return  new BaseResp(0,"密码错误!",null,null);
        }
        return new BaseResp(1,"success",user,null);
    }
}
